/**********************************************************************************
 * Copyright (c) 2012 - 2012,  parallel, All right reserved
 * Title: com.adc.parallel.daemon  ExecutorDaemonThread.java 
 * @author shen  shenqiao2012@163.com 
 *  2012-11-20 上午11:21:59 
 *********************************************************************************/


package com.adc.parallel.daemon;

import com.adc.parallel.constants.CompleteList;
import com.adc.parallel.constants.RuntimeList;
import com.adc.parallel.constants.SysConstants;
import com.adc.parallel.constants.ThreadConstant;
import com.adc.parallel.constants.WaitList;
import com.adc.parallel.dto.BaseTaskDto;
import com.adc.parallel.dto.CompletedTaskDto;
import com.adc.parallel.pool.BaseExecutorThread;
import com.adc.parallel.pool.ThreadPool;


/**
 * 
 * Description: the daemon of exexcutor thread
 * @author shen  shenqiao2012@163.com
 * @param <T>
 * @param <E>
 * @param <S>
 */
@SuppressWarnings("unchecked")
public class ExecutorDaemonThread<T extends BaseExecutorThread<E , S>, 
				E extends BaseTaskDto<S>, S> extends BaseTimerThread{
	private T executorThread;
	private E taskDto;
	private boolean flag=true;
	private String startTime;
	private String endTime;
	private CompletedTaskDto<S> completedTaskDto;

	
	/**
	 * 
	* @param executorThread
	* @param taskDto
	 */
	public ExecutorDaemonThread(T executorThread,final E taskDto) {
		super(ThreadConstant.getPersistentMaxAliveTime(), ThreadConstant.getPersistentCycle());
		this.setName(SysConstants.getDaemonThreadName(executorThread.getName()));
		this.executorThread=executorThread;
		this.taskDto=taskDto;
	}
	
	/**
	 * 
	* @param maxLive
	* @param cycle
	* @param executorThread
	* @param taskDto
	 */
	public ExecutorDaemonThread(final long maxLive,final long cycle,T executorThread,final E taskDto) {
		super(maxLive, cycle);
		this.setName(SysConstants.getDaemonThreadName(executorThread.getName()));
		this.executorThread=executorThread;
		this.taskDto=taskDto;
	}

	/**
	 * Description:  first time, set taskDto to exec-thread,set it to RT-list.
	 * @see com.adc.parallel.daemon.BaseTimerThread#operaPerCycle() 
	 */
	@Override
	public int operaPerCycle() {
		// TODO Auto-generated method stub
		int rs=ThreadConstant.EXEC_FAIL;
		if (flag) { // first time, set taskDto to exec-thread,set it to RT-list.
			executorThread.setTaskDto(taskDto);
			executorThread.start();
			RuntimeList.getRuntimeList().add(taskDto);
			flag=false;
		}else {
			rs=dealWithExecutorReturnInfo();  // Determine the execution status
		}
		return rs;
	}

	/**
	 * Description:  set resource equal null when thread is timeout
	 * @see com.adc.parallel.daemon.BaseTimerThread#operaOnTimeOut() 
	 */
	@Override
	public int operaOnTimeOut() {
		// TODO Auto-generated method stub
//		System.out.println("\t"+this.getName()+"\t is on the working!");
		int rs=ThreadConstant.EXEC_FAIL;
		if (executorThread!=null) {
			rs=dealWithExecutorReturnInfo();  // Determine the execution status
		}
		return rs;
	}

	/**
	 * @return the executorThread
	 */
	public T getExecutorThread() {
		return executorThread;
	}

	/**
	 * @param executorThread the executorThread to set
	 */
	public void setExecutorThread(T executorThread) {
		this.executorThread = executorThread;
	}
	
	/**
	 * 
	 * Description: deal with the return info of target executor thread
	 * author:  shen 
	 * @return int
	 */
	private int dealWithExecutorReturnInfo(){
		int rs=ThreadConstant.EXEC_FAIL;
		if (ThreadConstant.EXEC_SUCCESS==executorThread.getExecReturn()||
				ThreadConstant.EXEC_FAIL==executorThread.getExecReturn()) { // if success or failed
			rs=executorThread.getExecReturn();
			startTime=executorThread.getStartTime();
			endTime=executorThread.getCompleteTime();
			RuntimeList.removeTaskDto(taskDto);    //  remove taskDto from RT-list
			
			completedTaskDto=new CompletedTaskDto<S>(startTime, endTime,rs, taskDto);
			CompleteList.getCompleteList().add(completedTaskDto);  //  set completeDto to CP-list
			System.out.println("[Info]\t["+this.getName()+"] is ["+rs+"]! The info is:"+completedTaskDto.toString());
			
			ThreadPool.getCurrentPool().returnObject(
					ThreadPool.getThreadPoolFactory().clearObject(executorThread)); // destory executorThread
			this.setExit(true); //  当杀掉主线程、释放资源后，守护线程自杀！
			rs = ThreadConstant.EXEC_SUCCESS;
		}else if (SysConstants.Default_Exec_Return==executorThread.getExecReturn()) {  //  broken
			rs=executorThread.getExecReturn();
			endTime=executorThread.getCompleteTime();
			RuntimeList.removeTaskDto(taskDto);    //  remove taskDto from RT-list
			
			WaitList.insertBrokenTaskDto(taskDto);
			System.out.println("[Info]\t["+this.getName()+"] is TimeOut!");
			
			ThreadPool.getThreadPoolFactory().destroyObject(executorThread); // destory executorThread
			this.setExit(true); //  当杀掉主线程、释放资源后，守护线程自杀！
			rs = ThreadConstant.EXEC_SUCCESS;
		}
		return rs;
	}
	

}
